package com.project.poetry.common.job;

import cn.hutool.core.util.StrUtil;
import com.project.poetry.service.entity.po.job.JobPO;
import lombok.extern.slf4j.Slf4j;
import org.quartz.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

/**
 * @author mengxj
 */
@Component
@Slf4j
public class QuartzUtil {

    private QuartzUtil(){}

    private static final String JOB_KEY_PRE = "score_job_";

    private static final String TRIGGER_KEY_PRE = "score_trigger_";

    private static final String POETRY_GROUP_PRE = "score_group_";

    private static final String POETRY_DEFAULT_GROUP = "default";

    public static final String JOB_PARAM_KEY = "JOB_PARAM_KEY";

    private static Scheduler scheduler;

    @Autowired
    public void setScheduler(Scheduler scheduler){
        QuartzUtil.scheduler = scheduler;
    }

    private static Scheduler getScheduler(){
        return scheduler;
    }

    /**
     * 校验cron表达式是否符合规则
     * @param cronExpression cron表达式
     * @return 是否符合规则
     */
    public static boolean checkCron(String cronExpression){
        try {
            CronScheduleBuilder.cronSchedule(cronExpression);
            return true;
        }catch (RuntimeException e){
            return false;
        }
    }

    private static JobKey getJobKey(String jobId, String group){
        return JobKey.jobKey(JOB_KEY_PRE + jobId, POETRY_GROUP_PRE + group);
    }

    private static TriggerKey getTriggerKey(String jobId, String group){
        return TriggerKey.triggerKey(TRIGGER_KEY_PRE + jobId, POETRY_GROUP_PRE + group);
    }

    public static String getRealGroup(String group){
        if(StrUtil.isBlank(group)){
            return POETRY_DEFAULT_GROUP;
        }
        return group;
    }

    public static void createScheduler(JobPO jobEntity) throws SchedulerException {
        try {
            Scheduler scheduler = getScheduler();
            String jobId = jobEntity.getJobId(), group = jobEntity.getJobGroup();
            CronScheduleBuilder cronScheduleBuilder = CronScheduleBuilder.cronSchedule(jobEntity.getCronExpression()).withMisfireHandlingInstructionDoNothing();
            JobDetail jobDetail = JobBuilder.newJob(ScheduleJob.class).withIdentity(getJobKey(jobId, group)).build();
            jobDetail.getJobDataMap().put(JOB_PARAM_KEY, jobEntity);
            Trigger trigger = TriggerBuilder.newTrigger().withSchedule(cronScheduleBuilder).withIdentity(getTriggerKey(jobId, group)).build();
            scheduler.scheduleJob(jobDetail, trigger);
        }catch (SchedulerException e){
            log.error("创建定时任务失败 {}: {}", e.getClass(), e.getMessage());
            throw e;
        }
    }

    public static void updateScheduler(JobPO jobEntity) throws SchedulerException {
        try {
            Scheduler scheduler = getScheduler();
            String jobId = jobEntity.getJobId(), group = jobEntity.getJobGroup();
            TriggerKey tr = getTriggerKey(jobId, group);
            CronScheduleBuilder cronScheduleBuilder = CronScheduleBuilder.cronSchedule(jobEntity.getCronExpression()).withMisfireHandlingInstructionDoNothing();
            CronTrigger cronTrigger = (CronTrigger)scheduler.getTrigger(tr);
            Trigger trigger = cronTrigger.getTriggerBuilder().withSchedule(cronScheduleBuilder).build();
            trigger.getJobDataMap().put(JOB_PARAM_KEY, jobEntity);
            scheduler.rescheduleJob(tr, trigger);
        }catch (SchedulerException e){
            log.error("修改定时任务失败 {}: {}", e.getClass(), e.getMessage());
            throw e;
        }
    }

    public static void pauseScheduler(JobPO jobEntity) throws SchedulerException {
        try {
            Scheduler scheduler = getScheduler();
            scheduler.pauseJob(getJobKey(jobEntity.getJobId(), jobEntity.getJobGroup()));
        }catch (SchedulerException e){
            log.error("暂停定时任务失败 {}: {}", e.getClass(), e.getMessage());
            throw e;
        }
    }

    public static void resumeScheduler(JobPO jobEntity) throws SchedulerException {
        try {
            Scheduler scheduler = getScheduler();
            scheduler.resumeJob(getJobKey(jobEntity.getJobId(), jobEntity.getJobGroup()));
        }catch (SchedulerException e){
            log.error("恢复定时任务失败 {}: {}", e.getClass(), e.getMessage());
            throw e;
        }
    }

    public static void deleteScheduler(JobPO jobEntity) throws SchedulerException {
        try {
            Scheduler scheduler = getScheduler();
            scheduler.deleteJob(getJobKey(jobEntity.getJobId(), jobEntity.getJobGroup()));
        }catch (SchedulerException e){
            log.error("删除定时任务失败 {}: {}", e.getClass(), e.getMessage());
            throw e;
        }
    }

    public static void runScheduler(JobPO jobEntity) throws SchedulerException {
        try {
            Scheduler scheduler = getScheduler();
            JobKey jobKey = getJobKey(jobEntity.getJobId(), jobEntity.getJobGroup());
            JobDataMap data = new JobDataMap();
            data.put(JOB_PARAM_KEY, jobEntity);
            scheduler.triggerJob(jobKey, data);
        }catch (SchedulerException e){
            log.error("直接启动定时任务失败 {}: {}", e.getClass(), e.getMessage());
            throw e;
        }
    }

    public static void initScheduler(JobPO jobEntity) throws SchedulerException {
        try {
            Scheduler scheduler = getScheduler();
            JobKey jobKey = getJobKey(jobEntity.getJobId(), jobEntity.getJobGroup());
            JobDetail jobDetail = scheduler.getJobDetail(jobKey);
            if(jobDetail == null){
                createScheduler(jobEntity);
            }
        }catch (SchedulerException e){
            log.error("初始化定时任务失败 {}: {}", e.getClass(), e.getMessage());
            throw e;
        }
    }
}
